﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;

namespace HsServerHa.Utility.NetWork
{
    public class NetWorkHelper
    {

        /// <summary>
        /// 所有的网卡
        /// </summary>
        public static List<NetworkInterface>? adapters;
        public static NetworkInterface adapter;
        public static string adapterName;
        public static string CurrIPStr { get; set; }
        public static string VirtuallyIPStr { get; set; }
        public static string SubnetMaskStr { get; set; }
        public static string GatewayStr { get; set; }
        public static string DNS1Str { get; set; }
        public static string DNS2Str { get; set; }
        public static string MACStr { get; set; }

        /// <summary>
        /// IP验证
        /// 朱润来
        /// 2023年10月10日14:02:14
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        public static bool ValidateIpAddress(string ipAddress)
        {
            IPAddress ip = null;
            if (System.Net.IPAddress.TryParse(ipAddress, out ip))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 验证子网掩码
        /// 朱润来
        /// 2023年10月10日14:23:46
        /// </summary>
        /// <param name="mask"></param>
        /// <returns></returns>
        public static bool ValidateMask(string mask)
        {
            string[] vList = mask.Split('.');
            if (vList.Length != 4) return false;

            bool vZero = false; // 出现0 
            for (int j = 0; j < vList.Length; j++)
            {
                int i;
                if (!int.TryParse(vList[j], out i)) return false;
                if ((i < 0) || (i > 255)) return false;
                if (vZero)
                {
                    if (i != 0) return false;
                }
                else
                {
                    for (int k = 7; k >= 0; k--)
                    {
                        if (((i >> k) & 1) == 0) // 出现0 
                        {
                            vZero = true;
                        }
                        else
                        {
                            if (vZero) return false; // 不为0 
                        }
                    }
                }
            }

            return true;
        }

        /// <summary>
        /// 获取网关
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static string GetGateWay(IPInterfaceProperties ip)
        {
            string gateWay = "";
            GatewayIPAddressInformationCollection gateways = ip.GatewayAddresses;
            foreach (GatewayIPAddressInformation gateway in gateways)
            {
                if (IsPingIP(gateway.Address.ToString()))
                {
                    gateWay = gateway.Address.ToString();
                    break;
                }
            }
            return gateWay;
        }

        /// <summary>
        /// PINGIP地址
        /// 朱润来
        /// 2023年10月10日15:32:17
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsPingIP(string ip)
        {
            try
            {
                Ping ping = new Ping();
                PingReply reply = ping.Send(ip, 1000);
                if (reply != null)
                {
                    if (reply.Status != IPStatus.Success)
                    {
                        return false;
                    }
                }
                if (reply != null) { return true; } else { return false; }
            }
            catch
            {
                return false;
            }
        }


        /// <summary>
        /// 设置网络IP
        /// </summary>
        /// <param name="adapter"></param>
        /// <param name="ip"></param>
        /// <param name="submask"></param>
        /// <param name="gateway"></param>
        /// <param name="dns"></param>
        /// <returns></returns>
        private static bool SetIPAddress(NetworkInterface adapter, string[] ip, string[] submask, string[] gateway, string[] dns)
        {
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();
            string str = "";
            foreach (ManagementObject m in moc)
            {
                /*if (!(bool)m["IPEnabled"])
                    continue;*/
                if (m["SettingID"].ToString() == adapter.Id)
                {
                    if (ip != null && submask != null)
                    {
                        ManagementBaseObject inPar;
                        ManagementBaseObject outPar;
                        string caption = m["Caption"].ToString();
                        inPar = m.GetMethodParameters("EnableStatic");
                        inPar["IPAddress"] = ip;
                        inPar["SubnetMask"] = submask;
                        outPar = m.InvokeMethod("EnableStatic", inPar, null);
                        str = outPar["returnvalue"].ToString();
                        if (str != "0" && str != "1")
                        {
                            return false;
                        }
                    }
                    if (gateway != null)
                    {
                        ManagementBaseObject inPar;
                        ManagementBaseObject outPar;
                        string caption = m["Caption"].ToString();
                        inPar = m.GetMethodParameters("SetGateways");
                        inPar["DefaultIPGateway"] = gateway;
                        outPar = m.InvokeMethod("SetGateways", inPar, null);
                        str = outPar["returnvalue"].ToString();
                        if (str != "0" && str != "1")
                        {
                            return false;
                        }
                    }
                    if (dns != null)
                    {
                        ManagementBaseObject inPar;
                        ManagementBaseObject outPar;
                        inPar = m.GetMethodParameters("SetDNSServerSearchOrder");
                        inPar["DNSServerSearchOrder"] = dns;
                        outPar = m.InvokeMethod("SetDNSServerSearchOrder", inPar, null);
                        str = outPar["returnvalue"].ToString();
                        if (str != "0" && str != "1")
                        {
                            return false;
                        }
                    }
                    return true;
                }
            }
            return false;
        }




        /// <summary>
        /// 根据网卡名称寻找网卡信息
        /// 朱润来
        /// 2023年10月10日15:49:01
        /// </summary>
        /// <param name="adapterName"></param>
        /// <returns></returns>
        public static bool GetAdapterInfoDataByName(string adapterName)
        {
            adapter = GetAdapterByName(adapterName);
            if (adapter != null)
            {
                IPInterfaceProperties ip = adapter.GetIPProperties();
                UnicastIPAddressInformationCollection ipCollection = ip.UnicastAddresses;
                var index = 0;
                foreach (UnicastIPAddressInformation item in ipCollection)
                {
                    if (item.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        if (index > 0)
                        {
                            VirtuallyIPStr = item.Address.ToString();
                            continue;
                        }
                        CurrIPStr = item.Address.ToString();
                        SubnetMaskStr = item.IPv4Mask.ToString();
                        index++;
                    }
                }
                GatewayStr = GetGateWay(ip);
                if (ip.DnsAddresses.Count > 0)
                {
                    DNS1Str = ip.DnsAddresses[0].ToString();
                    if (ip.DnsAddresses.Count > 1)
                    {
                        DNS2Str = ip.DnsAddresses[1].ToString();
                    }
                    else
                    {
                        DNS2Str = "";
                    }
                }
                else
                {
                    DNS1Str = "";
                    DNS2Str = "";
                }
                PhysicalAddress pa = adapter.GetPhysicalAddress();
                byte[] bytes = pa.GetAddressBytes();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    sb.Append(bytes[i].ToString("X2"));
                    if (i != bytes.Length - 1)
                    {
                        sb.Append('-');
                    }
                }
                MACStr = sb.ToString();
            }
            else
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 获取所有的网卡
        /// </summary>
        /// <returns></returns>
        public static List<NetworkInterface> GetNetworkInfo()
        {
            adapters = new List<NetworkInterface>();
            foreach (NetworkInterface adapter in NetworkInterface.GetAllNetworkInterfaces())
            {
                adapters.Add(adapter);
            }
            return adapters;
        }

        /// <summary>
        /// 根据网卡名称获取网卡的属性
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static NetworkInterface GetAdapterByName(string name)
        {
            NetworkInterface adapter = null;
            foreach (NetworkInterface adapter2 in adapters)
            {
                if (adapter2.Name == name)
                {
                    adapter = adapter2;
                    break;
                }
            }
            return adapter;
        }


        /// <summary>
        /// 验证当前IP是否是本机
        /// </summary>
        /// <param name="ValIP"></param>
        /// <returns></returns>
        public static bool ValidateIPIsCurrIP(string ValIP)
        {
            //验证是否是本机IP
            var netlist = NetWorkHelper.GetNetworkInfo();
            foreach (var adapter in netlist)
            {
                IPInterfaceProperties ip = adapter.GetIPProperties();
                UnicastIPAddressInformationCollection ipCollection = ip.UnicastAddresses;
                foreach (UnicastIPAddressInformation item in ipCollection)
                {
                    if (item.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        if (ValIP == item.Address.ToString())
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 处理CMD命令
        /// </summary>
        /// <param name="cmd"></param>
        public static void HandleCMDCommand(string cmd)
        {
            Process process = new Process();
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = "cmd.exe";
            startInfo.Arguments = $"/c" + cmd;

            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardInput = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.CreateNoWindow = true;
            process.StartInfo = startInfo;

            startInfo.Verb = "RunAs";
            process.Start();
        }

        /// <summary>
        /// 添加防火墙例外端口
        /// </summary>
        /// <param name="fname">
        /// 名称
        /// </param>
        /// <param name="port">
        /// 端口
        /// </param>
        /// <param name="protocol">
        /// 协议(TCP、UDP)
        /// </param>
        public static bool NetFwAddPorts(string fname = "Ha心跳", int port = 6600, string protocol = "tcp")
        {
            try
            {

                if (IsInboundRuleExists(fname) == false)

                {
                    Process process = new Process();
                    process.StartInfo.FileName = "netsh";
                    process.StartInfo.Arguments = $"advfirewall firewall add rule name={fname} dir=in action=allow protocol={protocol} localport={port}"; // 替换为实际的命令参数
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.CreateNoWindow = true;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.Start();

                    string output = process.StandardOutput.ReadToEnd();
                    process.WaitForExit();
                    return true;

                }
                else
                {
                    return false;

                }
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(ex.Message+ex.ToString());
                return false;
            }
        }


        /// <summary>
        /// 判断是否有该入站规则
        /// </summary>
        /// <param name="ruleName"></param>
        /// <returns></returns>
        public static bool IsInboundRuleExists(string ruleName)
        {
            Process process = new Process();
            process.StartInfo.FileName = "netsh";
            process.StartInfo.Arguments = $"advfirewall firewall show rule name={ruleName}"; // 替换为实际的命令参数
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();

            string output = process.StandardOutput.ReadToEnd();
            bool ruleExists = output.Contains("已启用");
            process.WaitForExit();
            return ruleExists;
        }

        /// <summary>
        /// 验证两个IP是否同网段
        /// </summary>
        /// <param name="ip1"></param>
        /// <param name="ip2"></param>
        /// <returns></returns>
        public static bool ValidateIPIsWithNetworkSegment(string ip1, string ip2)
        {
            if (!ValidateIpAddress(ip1))
            {
                return false;
            }
            if (!ValidateIpAddress(ip2))
            {
                return false;
            }

            var ipStr1 = ip1.Split(".");
            var ipStr2 = ip2.Split(".");

            for (int i = 0; i < ipStr1.Length - 1; i++)
            {
                if (ipStr1[i] != ipStr2[i])
                {
                    return false;
                }
            }

            return true;
        }

        // 获取网卡接口索引
        public static int GetInterfaceIndex(string interfaceName)
        {
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in interfaces)
            {
                if (adapter.Name == interfaceName)
                {
                    IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
                    return adapterProperties.GetIPv4Properties().Index;
                }
            }
            return -1;
        }

        // P/Invoke声明
        [DllImport("iphlpapi.dll", SetLastError = true)]
        public static extern int AddIPAddress(string ipAddress, string ipMask, int ifIndex, out int NTEContext, out int NTEInstance);
        [DllImport("iphlpapi.dll", EntryPoint = "AddIPAddress", SetLastError = true)]
        public static extern int AddVirtualIPAddress(UInt32 ipAddress, UInt32 ipMask, int ifIndex, out int NTEContext, out int NTEInstance);

        //[DllImport("iphlpapi.dll", SetLastError = true)]
        //public static extern int DeleteIPAddress(int NTEContext);

        // 声明DeleteIPAddress函数
        [DllImport("iphlpapi.dll", SetLastError = true)]
        private static extern int DeleteIPAddress(IntPtr ipAddress);

        [DllImport("iphlpapi.dll", SetLastError = true)]
        private static extern int DeleteIPAddress(UInt32 ipAddress);

        /// <summary>
        /// 删除虚拟IP地址
        /// </summary>
        /// <param name="ipStr"></param>
        /// <returns></returns>
        public static int DeleteVirtualIP(string ipStr)
        {

            if (string.IsNullOrEmpty(ipStr))
            {
                return -1;
            }
            var ipAddress = IPAddress.Parse(ipStr);


            int result = DeleteIPAddress((uint)BitConverter.ToInt32(ipAddress.GetAddressBytes(), 0));

            return result;
        }

        /// <summary>
        /// 验证IP是否是固定IP
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        public static bool IsStaticIP(string ipAddress)
        {
            bool isStatic = false;

            //foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
            //{
            //    IPInterfaceProperties ipProperties = netInterface.GetIPProperties();
            //    foreach (UnicastIPAddressInformation unicastAddress in ipProperties.UnicastAddresses)
            //    {
            //        if (unicastAddress.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            //        {
            //            if (unicastAddress.Address.ToString() == ipAddress)
            //            {
            //                isStatic = unicastAddress.IsDnsEligible;
            //                break;
            //            }
            //        }
            //    }
            //}
            NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

            foreach (NetworkInterface networkInterface in networkInterfaces)
            {
                if (networkInterface.OperationalStatus == OperationalStatus.Up)
                {
                    IPInterfaceProperties ipProperties = networkInterface.GetIPProperties();
                    foreach (UnicastIPAddressInformation ip in ipProperties.UnicastAddresses)
                    {
                        if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            if (ip.Address.ToString() == ipAddress)
                            {
                                if (ip.PrefixOrigin == System.Net.NetworkInformation.PrefixOrigin.Dhcp)
                                {
                                    isStatic = false;
                                }
                                else
                                {
                                    isStatic = true;
                                }
                                break;
                            }

                        }
                    }
                }
            }

            return isStatic;
        }


        /// <summary>
        /// 验证虚拟IP地址是否在本地存在
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        public static bool IsVirtualIPExists(string ipAddress)
        {
            bool exists = false;

            foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
            {
                IPInterfaceProperties ipProperties = netInterface.GetIPProperties();
                foreach (UnicastIPAddressInformation unicastAddress in ipProperties.UnicastAddresses)
                {
                    if (unicastAddress.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    {
                        if (unicastAddress.Address.ToString() == ipAddress)
                        {
                            exists = true;
                            break;
                        }
                    }
                }
            }

            return exists;
        }


        public static ManagementObject? GetNetAdapter(string name)
        {
            using (ManagementClass mc = new ManagementClass("Win32_NetworkAdapter"))
            {
                var ns = mc.GetInstances().Cast<ManagementObject>().Where(x => x["NetEnabled"] != null && (bool)x["NetEnabled"] == true).ToList();
                return ns.Where(x => (string)x["Name"] == name).FirstOrDefault();
            }
        }
        public static int SetMacAddress(string adapterName, string newMac)
        {
            ManagementObject? mo = GetNetAdapter(adapterName);
            if (mo == null) return -1;

            uint index = (uint)mo["Index"];
            SetMacAddress(index, newMac);

            try
            {
                mo.InvokeMethod("Disable", null);
                mo.InvokeMethod("Enable", null);
            }
            catch
            {
                return -2;
            }
            return 0;
        }
        public static void SetMacAddress(uint index, string newMac)
        {
            //得到 MAC的注册表键
            RegistryKey? macRegistry = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}").
                OpenSubKey(index.ToString().PadLeft(4, '0'), true);
            if (macRegistry == null) return;

            if (string.IsNullOrEmpty(newMac))
            {
                macRegistry.DeleteValue("NetworkAddress");
            }
            else
            {
                macRegistry.SetValue("NetworkAddress", newMac);
                //macRegistry.OpenSubKey("Ndi", true).OpenSubKey("params", true).OpenSubKey("NetworkAddress", true).SetValue("Default", newMac);
                //macRegistry.OpenSubKey("Ndi", true).OpenSubKey("params", true).OpenSubKey("NetworkAddress", true).SetValue("ParamDesc", "Network Address");
            }
        }
    }
}
